﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SilverPOP.Data.Process.Entity;
using SilverPOP.Data.Process.BLL;
using Helpers;
using Utilities;
using Atp.Net;
using SilverPOP.Library.BusinessEntities;
using System.Xml;
using System.Threading;
using System.Data;
using SilverPOP.Data.Process.Helpers.XmlConverter;

namespace SilverPOP.Data.Process.OperationUnit
{
    public class DataUpdateProcess : DataAndSchemaProcess
    {
        #region Fields
        private  long _totalResponder = 0;
       // private  List<Responders> _responderList=null;
        private List<String> uploadingFTPFileNames = new List<string>();
        private DateTime _dataUpdateDate;
        #endregion

       #region Constructor
        //public DataUpdateProcess(long campaignId)
        //{
        //    this.campaignId = campaignId;
        //    this.CreateFolder(ConfigHelpers.LocalSilverPOPDataUpdateDirectoryName);
        //}

        List<DatabaseSchemaEntity> _databaseSchemaEntity = null;
        public DataUpdateProcess(TaskListEntity task)
        {
                       _databaseSchemaEntity = BLL.DatabaseSchema.GetDatabaseSchemaByProjectId(task.ProjectId);
                       DAL.DAL.SetConnectionString(task.ServerName, task.DatabaseName, task.Username, task.Password);
                       this.CreateFolder(ConfigHelpers.LocalUploadDirectoryName + @"\" + task.ProjectName);
                       this.campaignId = task.CampaignId;                                
        }
        #endregion  
        
        public override void ExecuteOperation()
        {

            //try
            //{
                this.processStartingTime = DateTime.Now.TimeOfDay;
                Console.WriteLine("Responders, opt out and bounced data update process in SilverPOP started.");

                //UpdateDataInSilverPOPDatabase();
                List<ContactListCreationEntity> contactEntityCreationList = new List<ContactListCreationEntity>();
                GetRespondersOptOutOrBounceList(contactEntityCreationList);

                Console.WriteLine("Responders, opt out and bounced data update process in SilverPOP completed.");
                Console.WriteLine("Total Responders: " + _totalResponder);

                FileWriter.WriteToFile(this.successFileNameWithPath, "Total Responders: " + _totalResponder);
                this.CalculateTotalProcessingTime();
                
            //}
            //catch (Exception ex)
            //{
            //    this.LogError(ex);
            //    throw ex;
            //}

        }

      

        #region Importing Non Responder Data  In SilverPOP Database
        private void GetRespondersOptOutOrBounceList(List<ContactListCreationEntity> contactEntityCreationList)
        {
            List<String> uploadingFileNames = new List<string>();
            contactEntityCreationList = DataUpdateBLL.PopulateContactEntityCreationObjects(this.campaignId);

            if (GetRespondersAndDoRelatedTask(uploadingFileNames, contactEntityCreationList)) // Get  responders list from DB and then generate CSV and xml mapper file
            {
                if (UploadFileInSilverPOPFTP(uploadingFileNames)) //Upload generated csv file and xml mapper to SilverPOP FTP Server
                {
                    ImportDataToSilverPOPDatabase(uploadingFileNames); // Import data in SilverPOP Database
                }
            }

        }

        #region Get All Non Responders and Generate CSV Files and Their Related XML Schema Mapper
        private bool GetRespondersAndDoRelatedTask(List<String> uploadingFTPFileNames, List<ContactListCreationEntity> contactEntityCreationList)
        {
            _dataUpdateDate = DateTime.Now;
            //Though foreach loop is used but it will be only one campaign for every time
            //because we provide campaign id from console input
            foreach (ContactListCreationEntity contactEntity in contactEntityCreationList)
            {

                Console.WriteLine("Responders members data fetching started from Database for CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID);

               // _responderList = DataUpdateBLL.GetRespondersAndOptOutAndBounced(contactEntity.CampaignAndItsBlast.Campaign.CampaignID,this.errorFileNameWithPath);

                DataTable responderDataTable = DataUpdateBLL.GetRespondersAndOptOutAndBouncedDataTable(contactEntity.CampaignAndItsBlast.Campaign.CampaignID, this.errorFileNameWithPath);

                Console.WriteLine("Responders data fetching completed for CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID + " and campaign name: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignName);
                FileWriter.WriteToFile(this.successFileNameWithPath, "Responders data fetching completed for CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID + " and campaign name: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignName);

                if (responderDataTable != null)
                if (contactEntity.Segment != null  && responderDataTable.Rows.Count > 0)
                {
                    _totalResponder += responderDataTable.Rows.Count;

                    FileWriter.WriteToFile(this.successFileNameWithPath, "Total responders for Campaign: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignName + " is: " + responderDataTable.Rows.Count);

                    foreach (Segment segment in contactEntity.Segment)
                    {

                 //List<Responders> filterNonResponderBySegment =     _responderList.Where(x => x.Segment.ToLower() == segment.SegmentCode.ToLower()).ToList();
                        DataTable filterResponderBySegment = responderDataTable.AsEnumerable().Where(x => x.Field<string>("Segment").ToLower() == segment.SegmentCode.ToLower()).CopyToDataTable();

                        if (filterResponderBySegment != null)
                            if (filterResponderBySegment.Rows.Count > 0)
                        {
                            String fileName = contactEntity.SilverPOPDatabaseID + "-" + segment.SegmentCode + "_" + DateTime.Now.ToShortDateString().Replace(@"/", "") + DateTime.Now.Millisecond.ToString() + ".csv";
                            uploadingFTPFileNames.Add(fileName);
                            CreateCSVFileAndItsRelatedMapperXMLFile(filterResponderBySegment, fileName, contactEntity.SilverPOPDatabaseID, segment);
                            FileWriter.WriteToFile(this.successFileNameWithPath, "Responders count for Segment: " + segment.SegmentCode + " is: " + filterResponderBySegment.Rows.Count);
                        }
                    }

                    //Keep Log Which Prospets Data are updated in SilverPOP
                    //MarkedUpdatedDataInLocalDatabase(_responderList, _dataUpdateDate);
                }

                if (responderDataTable == null)
                {
                    Console.WriteLine("No Responders found for CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID);
                    FileWriter.WriteToFile(this.errorFileNameWithPath, "No Responders found for CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID);
                    return false;
                }

                if (contactEntity.Segment == null)
                {
                    Console.WriteLine("Segment not found CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID);
                    FileWriter.WriteToFile(this.errorFileNameWithPath, "Segment not found CampaignID: " + contactEntity.CampaignAndItsBlast.Campaign.CampaignID);
                    return false;
                }
            }

            return true;
        }

     
  

        private void CreateCSVFileAndItsRelatedMapperXMLFile(DataTable responderDataTable, String fileName, long databaseId, Segment segment)
        {
            CsvUtility.ExportDataTableToCSVAndSaveInFolder(responderDataTable, ",", this.directoryName, fileName);
            //CsvUtility.ExportDataTableToCSVAndSaveInFolder(nonResponderDataTable, ",", this.directoryName, fileName);
            Console.WriteLine("Csv file created. File Name is: " + fileName);

            FileWriter.WriteToFile(this.successFileNameWithPath, "Csv file created. File Name is: " + fileName);

            //CSV file created, now we will create schema definition for this file
          //  String schmeaText = File.ReadAllText(ConfigHelpers.SchemaMapperFileWithOutContactList);

            String schmeaText = XmlConverterHelpers.GetConvertedXmlFile(_databaseSchemaEntity,false);
            schmeaText = schmeaText.Replace("###Action###", ActionType.ADD_AND_UPDATE.ToString());
            schmeaText = schmeaText.Replace("###ListID###", databaseId.ToString());
            schmeaText = schmeaText.Replace("###ListVisibility###", ((int)ListVisibility.Shared).ToString());
            schmeaText = schmeaText.Replace("###FileType###", ((int)FileType.CSV).ToString());

            String mapperfileName = fileName.Replace(".csv", ".xml");
            String schemaFileNameWithPath = this.directoryName + @"\" + mapperfileName;

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(schmeaText);
            doc.PreserveWhitespace = true;
            doc.Save(schemaFileNameWithPath);

            Console.WriteLine("XML mapper file for CSV: {0}  is created. Mapper File Name is: {1} ", fileName, mapperfileName);
            FileWriter.WriteToFile(this.successFileNameWithPath, "XML mapper file for CSV file: " + fileName + "  is created. Mapper File Name is: " + mapperfileName);
        }
        #endregion


        #region Upload File In SilverPOP FTP
        private bool UploadFileInSilverPOPFTP(List<String> uploadingFTPFileNames)
        {

            if (uploadingFTPFileNames != null && uploadingFTPFileNames.Count > 0)
            {
                Console.WriteLine("Conecting to FTP...");
                FileWriter.WriteToFile(this.successFileNameWithPath, "Conecting to FTP...");

                String remoteLocation = String.Empty;
                String localLocation = this.directoryName;

                Sftp client = new Sftp();
                client.Connect(ConfigHelpers.FTPHost, ConfigHelpers.FTPPort);
                client.Authenticate(ConfigHelpers.FTPUserName, ConfigHelpers.FTPPassword);


                if (client.IsConnected)
                {
                    Console.WriteLine("Successfully connected to FTP.");
                    FileWriter.WriteToFile(this.successFileNameWithPath, "Successfully connected to FTP.");

                    client.KeepAlive();
                    String defaultDir = client.GetCurrentDirectory();
                    defaultDir += ConfigHelpers.FTPUploadDirectoryName;

                    Console.WriteLine("File uploading is going to start...");

                    foreach (String uploadingFileName in uploadingFTPFileNames)
                    {
                        String xmlMapperFileName = uploadingFileName.Replace(".csv", ".xml");


                        //local file name with path csv file and xml mapper
                        String localCSVFileNameWithPath = localLocation + @"\" + uploadingFileName;
                        String localXMLMapperFileNameWithPath = localLocation + @"\" + xmlMapperFileName;


                        //remote file name with path csv file and xml mapper
                        String remoteCSVFileNameWithPath = defaultDir + @"/" + uploadingFileName;
                        String remoteXMLMapperFileNameWithPath = defaultDir + @"/" + xmlMapperFileName;

                        if (File.Exists(localCSVFileNameWithPath))
                        {
                            Console.WriteLine("File uploading is going on ...");

                            long identifier = client.UploadFile(localCSVFileNameWithPath, remoteCSVFileNameWithPath);
                            long identifier2 = client.UploadFile(localXMLMapperFileNameWithPath, remoteXMLMapperFileNameWithPath);


                            Thread.Sleep(ConfigHelpers.WaitingTimePerFile);


                            Console.WriteLine("CSV File uploaded successfully. File name is: " + uploadingFileName);
                            Console.WriteLine("XML Mapper File uploaded successfully. File name is: " + xmlMapperFileName);

                            FileWriter.WriteToFile(this.successFileNameWithPath, "CSV File uploaded successfully. File name is: " + uploadingFileName);
                            FileWriter.WriteToFile(this.successFileNameWithPath, "XML Mapper File uploaded successfully. File name is: " + xmlMapperFileName);

                        }


                    }

                    client.KeepAlive();

                }

                //wait for one minute
                Console.WriteLine("Wait uploading is going on ...");
                Thread.Sleep(ConfigHelpers.OverAllWaitingTime);
                Console.WriteLine("File uploading completed.");
                return true;
            }
            else
            {
                Console.WriteLine("There is no file for uploading...");
                FileWriter.WriteToFile(this.errorFileNameWithPath, "There is no file for uploading.");
                return false;
            }

        }

        #endregion

        #region Import Data In SilverPOP Database
        private void ImportDataToSilverPOPDatabase(List<String> uploadingFTPFileNames)
        {
            Console.WriteLine("Data sync is going to start in SilverPOP Database ...");
            SilverPopAccount silverPopAccount = this.InstanceSilverPOPAccount;

            if (silverPopAccount != null)
            {
                Console.WriteLine("Data sync is started ...");
                FileWriter.WriteToFile(this.successFileNameWithPath, "Data sync is started in SilverPOP Database.");
                Dictionary<String, String> importResult = SilverPOP.Library.Helpers.SilverPopHelpers.ImportDataToSilverPOPDatabase(silverPopAccount, uploadingFTPFileNames);

                if (importResult != null && importResult.Count > 0)
                {
                    foreach (KeyValuePair<String, String> keyValue in importResult)
                    {
                        if (keyValue.Key == "Error")
                        {
                            Console.WriteLine(keyValue.Value);
                            FileWriter.WriteToFile(this.errorFileNameWithPath, "Error during importing data in SilverPOP: " + keyValue.Value);
                        }
                        else
                        {
                            String[] keyValueArray = keyValue.Value.Split('-');
                            //if (keyValueArray.Length < 2)
                            //{
                            //    Console.WriteLine("File name: " + keyValue.Key + " :" + keyValue.Value);
                            //    FileWriter.WriteToFile(this.successFileNameWithPath, "File name: " + keyValue.Key + " :" + keyValue.Value);
                            //}
                            //else if (keyValueArray.Length == 2)
                            //{
                                Console.WriteLine("File name: " + keyValue.Key + " :" + keyValueArray[0] + "  and Job ID: " + keyValueArray[1]);
                                FileWriter.WriteToFile(this.successFileNameWithPath, "File name: " + keyValue.Key + " :" + keyValueArray[0] + "  and Job ID: " + keyValueArray[1]);
                            //}
                        }
                    }
                }
            }
            else
            {
                throw new Exception("SilverPOP account not found.");
            }

            Console.WriteLine("Data sync in SilverPOP Database has completed.");
        }
        #endregion

        #endregion

        #region Commented Code
        /*
        #region Start Update Process
        private  void UpdateDataInSilverPOPDatabase()
         {
             List<CampaignWithBlast> campaignWithBlast = DataUpdateBLL.GetActiveCampaignWithItsBlast(this.campaignId);

             if (campaignWithBlast != null)
             {
                 foreach (CampaignWithBlast campaign in campaignWithBlast)
                 {
                     UpdateContactInSilverPOP(campaign.Campaign.CampaignID);
                 }
             }
         }
        #endregion

        #region Update Data In SilverPOP Database

        private void UpdateContactInSilverPOP(long campaignID)
         {
            _responderList = DataUpdateBLL.GetRespondersAndOptOutAndBounced(campaignID);

            if (_responderList == null)
            {
                Console.WriteLine("There is no responder found for campaign ID: " + campaignID+" to update data in SilverPOP database.");
                FileWriter.WriteToFile(this.successFileNameWithPath, "There is no responder found for campaign ID: " + campaignID + " to update data in SilverPOP database.");
            }
            else
            {
                List<UpdatingSilverPOPContact> updateSilverPOPContactList = new List<UpdatingSilverPOPContact>();

                foreach (Responders responder in _responderList)
                {
                    UpdatingSilverPOPContact updateSilverPOPContact = new UpdatingSilverPOPContact("ProspectId", responder.ProspectId.ToString());
                    updateSilverPOPContact.UpdatingColumnNameValueList.Add(new UpdatingColumnNameValue(responder.UpdatingColumnName,responder.UpdatingColumnValue));

                    updateSilverPOPContactList.Add(updateSilverPOPContact);
                }

                if (updateSilverPOPContactList != null && updateSilverPOPContactList.Count > 0)
                {
                    long currentCampaignActiveDatabaseID = DataUpdateBLL.GetCurrentCampaignActiveSilverPOPDatabaseID(campaignID);

                    if (currentCampaignActiveDatabaseID > 0)
                    {
                        Console.WriteLine("Login to SilverPOP Account.");
                        FileWriter.WriteToFile(this.successFileNameWithPath, "Login to SilverPOP Account.");

                        List<UpdateResult> resultList = SilverPopHelpers.UpdateRecipientData(this.InstanceSilverPOPAccount, currentCampaignActiveDatabaseID, updateSilverPOPContactList);
                       
                        MarkedUpdatedDataInLocalDatabase(resultList);
                    }
                    else
                    {
                        FileWriter.WriteToFile(this.errorFileNameWithPath, "There is no SilverPOP active database id found for campaign ID: "+campaignID);
                    }
                }
                else
                {
                    FileWriter.WriteToFile(this.errorFileNameWithPath, "Can not able to create UpdatingSilverPOPContact list object. Please check the logic.");
                }
            }
        }
       #endregion
        */
        #endregion

        //#region Mark SilverPOP Updated Data In Our Local Database
        //private void MarkedUpdatedDataInLocalDatabase(List<Responders> respondersList,DateTime updateDate)
        //{
        //     String updateType=String.Empty;

        //    foreach (Responders responder in respondersList)
        //    {
        //        updateType = String.Empty;
                
        //        if (responder.IsSubmitted == 1)
        //            updateType = UpdatedDataValue.Submitted.ToString();
        //        else if (responder.IsSubscribed == 1)
        //            updateType = UpdatedDataValue.OptedOut.ToString();
        //        else if(responder.IsBounced == 1)
        //            updateType = UpdatedDataValue.Bounced.ToString();
        //        else if (responder.IsDeleted == 1)
        //            updateType = UpdatedDataValue.Deleted.ToString();


        //        if (!String.IsNullOrEmpty(updateType))
        //        {
        //            Console.WriteLine("Updated Contact ID: " + responder.ProspectId + " Update For: " + updateType);
        //            DataUpdateBLL.MarkedDataInDatabase(Convert.ToInt64(responder.ProspectId), updateType,updateDate);
        //            FileWriter.WriteToFile(this.successFileNameWithPath, "Updated Contact ID: " + responder.ProspectId + " Update For: " + updateType);
        //        }
                
        //    }
        //}
        //#endregion
         
        

       

    }//end class
}
